﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Schema;
using System.Xml;
using System.IO;
using CUILoader;

namespace FUI
{
    public abstract class FUIBase:IFUI
    {
        #region Properties
        private List<CAttribute> lstAttributes;
        public List<CAttribute> LstAttributes
        {
            get { return lstAttributes; }
            set { lstAttributes = value; }
        }

        private string strName;
        public string StrName
        {
            get { return strName; }
            set { strName = value; }
        }

        protected XmlSchema controlXMLSchema;

        private XmlDocument controlXMLDocument;
        public XmlDocument ControlXMLDocument
        {
            get { return controlXMLDocument; }
            set { controlXMLDocument = value; }
        }

        //Get path của .dll hiện tại
        string strPath;
        public string StrPath
        {
            get { return strPath; }
            set { strPath = value; }
        }
        
        public string getName()
        {
            return strName;
        }


        public List<CAttribute> getAttributes()
        {
            return lstAttributes;
        }

        #endregion

        #region Methods
        public FUIBase()
        {
            strName = "myControl";
            lstAttributes = new List<CAttribute>();
            controlXMLSchema = new XmlSchema();
            controlXMLDocument = new XmlDocument();

            strPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
            strPath = strPath.Substring(0, strPath.LastIndexOf("\\")) + @"\Plugins\FUIPlugins";

        }

        public bool loadXMLProperties()
        {
            try
            {               
                XmlReader reader = XmlReader.Create(strPath + "\\" +strName + ".xml");
                controlXMLDocument.Load(reader);

                if (!Validate())
                    return false;

                //Add Att to lstAttributes
                XmlNodeList AttributesElement = controlXMLDocument.GetElementsByTagName("Attributes");
                XmlNodeList listAttributesNodes = AttributesElement[0].ChildNodes;
                foreach (XmlNode n in listAttributesNodes)
                {
                    string strTemp = n.Name;
                    if (strTemp == "ItemCollection")
                    {
                        XmlNodeList listItem = n.ChildNodes;
                        XmlDocument xmlDocumentItem = new XmlDocument();
                        XmlElement eleRoot = xmlDocumentItem.CreateElement("ItemCollection");

                        foreach (XmlNode nn in listItem)
                        {
                            XmlElement ele = xmlDocumentItem.CreateElement("Item");
                            XmlAttribute attName = xmlDocumentItem.CreateAttribute("ItemName");
                            attName.Value = nn.Attributes["ItemName"].Value;
                            ele.Attributes.Append(attName);

                            XmlAttribute attValue = xmlDocumentItem.CreateAttribute("ItemValue");
                            attValue.Value = nn.Attributes["ItemValue"].Value;
                            ele.Attributes.Append(attValue);

                            XmlAttribute attText = xmlDocumentItem.CreateAttribute("ItemText");
                            attText.Value = nn.Attributes["ItemText"].Value;
                            ele.Attributes.Append(attText);

                            eleRoot.AppendChild(ele);
                        }
                        xmlDocumentItem.AppendChild(eleRoot);

                        CAttribute newAtt = new CAttribute();
                        newAtt.StrName = "ItemCollection";
                        StringWriter sw = new StringWriter();
                        XmlTextWriter w = new XmlTextWriter(sw);
                        xmlDocumentItem.Save(w);
                        newAtt.StrValue = sw.ToString();
                        newAtt.ValueType = eType.ItemsCollection;
                        lstAttributes.Add(newAtt);
                    }
                    else
                    {
                        CAttribute newAtt = new CAttribute();
                        newAtt.StrName = n.Name;
                        newAtt.StrValue = n.Attributes["Value"].Value;
                        newAtt.ValueType = CUIBase.TypeValueParser(n.Attributes["ValueType"].Value);
                        lstAttributes.Add(newAtt);
                    }
                    
                }

                return true;
            }
            catch (Exception exp){
                return false; }
        }

        public bool Validate()
        {

            bool isValide = true;
            try
            {
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.Schemas.Add("urn:myControl", strPath + "\\" + strName + ".xsd");
                settings.ValidationType = ValidationType.Schema;
                XmlReader rdr = XmlReader.Create(new StringReader(controlXMLDocument.InnerXml), settings);
                while (rdr.Read()) { }
            }
            catch(Exception exp)
            {
                isValide = false;
            }
            return isValide;
        }

        public bool toXML()
        {
            try
            {
                string file = StrName + ".xml";
                FileStream fs = new FileStream(file, FileMode.Create);
                XmlTextWriter w = new XmlTextWriter(fs, null);
                w.WriteStartDocument();

                w.WriteStartElement(StrName);

                w.WriteComment("This xml file generated for " + StrName + " UI");

                foreach (CAttribute item in LstAttributes)
                {
                    if (item.ValueType == eType.XML)
                    {
                        w.WriteStartElement("ItemCollection");
                        w.WriteAttributeString("ValueType", item.ValueType.ToString());

                        XmlDocument xmlDoc = new XmlDocument();
                        xmlDoc.LoadXml(item.StrValue);
                        if (xmlDoc.GetElementsByTagName("Item").Count > 0)
                        {
                            foreach (XmlNode node in xmlDoc.GetElementsByTagName("Item"))
                            {
                                w.WriteStartElement("Item");
                                w.WriteAttributeString("ItemName", node.Attributes["ItemName"].Value);
                                w.WriteAttributeString("ItemValue", node.Attributes["ItemValue"].Value);
                                w.WriteAttributeString("ItemText", node.Attributes["ItemText"].Value);
                                w.WriteEndElement();
                            }
                        }
                        w.WriteEndElement();
                    }
                    else
                    {
                        w.WriteStartElement(item.StrName);
                        w.WriteAttributeString("Value", item.StrValue);
                        w.WriteAttributeString("ValueType", item.ValueType.ToString());
                        w.WriteEndElement();
                    }
                }

                // Close the root element.
                w.WriteEndElement();

                w.WriteEndDocument();
                w.Close();

                return true;
            }
            catch (Exception exp)
            {
                return false;
            }
        }

        public bool fromXML()
        {
            try
            {
                string file = StrName + ".xml";
                FileStream fs = new FileStream(file, FileMode.Open);
                XmlTextReader r = new XmlTextReader(fs);

                XmlDocument xmlDoc = new XmlDocument();
                XmlElement eleRoot = xmlDoc.CreateElement("Items");
                XmlAttribute attValueType = xmlDoc.CreateAttribute("ValueType");
                attValueType.Value = eType.XML.ToString();
                eleRoot.Attributes.Append(attValueType);

                while (r.Read())
                {
                    if (r.NodeType == XmlNodeType.Element)
                    {
                        if (r.Name == "Item")
                        {
                            XmlElement ele = xmlDoc.CreateElement("Item");
                            XmlAttribute attName = xmlDoc.CreateAttribute("ItemName");
                            attName.Value = r.GetAttribute("ItemName");
                            ele.Attributes.Append(attName);
                            XmlAttribute attValue = xmlDoc.CreateAttribute("ItemValue");
                            attValue.Value = r.GetAttribute("ItemValue");
                            ele.Attributes.Append(attValue);
                            XmlAttribute attText = xmlDoc.CreateAttribute("ItemText");
                            attText.Value = r.GetAttribute("ItemText");
                            ele.Attributes.Append(attText);
                            eleRoot.AppendChild(ele);
                        }
                        foreach (CAttribute item in LstAttributes)
                        {
                            if (r.Name == item.StrName)
                            {
                                item.StrValue = r.GetAttribute(0);
                                item.ValueType = CUIBase.TypeValueParser(r.GetAttribute(1));
                            }
                        }
                    }
                }
                xmlDoc.AppendChild(eleRoot);
                LstAttributes[LstAttributes.Count - 1].StrName = "ItemCollection";
                LstAttributes[LstAttributes.Count - 1].ValueType = eType.XML;
                StringWriter sw = new StringWriter();
                XmlTextWriter w = new XmlTextWriter(sw);
                xmlDoc.Save(w);
                LstAttributes[LstAttributes.Count - 1].StrValue = sw.ToString();
                fs.Close();
                
                return true;
            }
            catch (Exception exp)
            {
                return false;
            }
        }

        public CAttribute getAttributeFromName(string strAttributeName)
        {
            foreach (CAttribute item in LstAttributes)
            {
                if (item.StrName == strAttributeName)
                {
                    return item;
                }
            }
            return null;
        }

        #endregion

        abstract public  string generateDeclaration();

        abstract public string generateInitialization();

        //Ham tra ve kieu du lieu tuong ung cho tung ngon ngu
        abstract public string generateDataType(CAttribute m_Att);
    }
}
